package me.cabbit.digitone.tones.speedlines;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.w3c.dom.Element;

import me.cabbit.digitone.support.Strings;

public class SpeedlinesPanel extends Speedlines implements ChangeListener, ActionListener {
	
	//------------------------------------------------------------------//
	//--------------------------- properties ---------------------------//
	//------------------------------------------------------------------//

	/** Options panel. This gets added to the main window's toolbox */	
	private JPanel panel;

	/** Strings for internationalization */	
	private Strings strings;
	
	private JSpinner spnNumberLines;
	private JSpinner spnMaxWidth;
	private JSpinner spnDisplacement;
	private JSpinner spnCenterX;
	private JSpinner spnCenterY;
	private JSpinner spnRadius1;
	private JSpinner spnRadius2;
	private JLabel lblSeed;

	/** A flag to indicate a preset is being loaded. Used to
	 * temporarily refresh the interface without triggering
	 * events
	 */
	private boolean isLoadingPreset;
	
	public SpeedlinesPanel() throws FileNotFoundException {
		//load strings
		this.strings = new Strings("lang/Speedlines.strings");
		Strings str = this.strings;
	
		//build panel
		this.panel = new JPanel();
		
		//set layout and constraints
		//Set layout and prepare constraints
		this.panel.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.insets = new Insets(3, 3, 3, 3);
		c.fill = GridBagConstraints.HORIZONTAL;
		
		//Center x
		c.gridx = 0; c.gridy++; c.weightx = 0.25;
		this.panel.add(new JLabel(str.get("OPTION_CENTER_X")), c);
		
		c.gridx = 1; c.weightx = 0.75;
		this.spnCenterX = new JSpinner(new SpinnerNumberModel(0, 0, null, 1));
		this.spnCenterX.setValue(this.getCenterX());
		this.spnCenterX.addChangeListener(this);
		this.panel.add(this.spnCenterX, c);		
		
		//Center y
		c.gridx = 0; c.gridy++; c.weightx = 0.25;
		this.panel.add(new JLabel(str.get("OPTION_CENTER_Y")), c);
		
		c.gridx = 1; c.weightx = 0.75;
		this.spnCenterY = new JSpinner(new SpinnerNumberModel(0, 0, null, 1));
		this.spnCenterY.setValue(this.getCenterY());
		this.spnCenterY.addChangeListener(this);
		this.panel.add(this.spnCenterY, c);		

		//Radius one
		c.gridx = 0; c.gridy++; c.weightx = 0.25;
		this.panel.add(new JLabel(str.get("OPTION_RADIUS_1")), c);
		
		c.gridx = 1; c.weightx = 0.75;
		this.spnRadius1 = new JSpinner(new SpinnerNumberModel(1, 0, null, 1));
		this.spnRadius1.setValue(this.getRadiusA());
		this.spnRadius1.addChangeListener(this);
		this.panel.add(this.spnRadius1, c);		

		//Radius two
		c.gridx = 0; c.gridy++; c.weightx = 0.25;
		this.panel.add(new JLabel(str.get("OPTION_RADIUS_2")), c);
		
		c.gridx = 1; c.weightx = 0.75;
		this.spnRadius2 = new JSpinner(new SpinnerNumberModel(1, 0, null, 1));
		this.spnRadius2.setValue(this.getRadiusB());
		this.spnRadius2.addChangeListener(this);
		this.panel.add(this.spnRadius2, c);		

		//number of lines
		c.gridx = 0; c.gridy++; c.weightx = 0.25;
		this.panel.add(new JLabel(str.get("OPTION_NUMBER_LINES")), c);
		
		c.gridx = 1; c.weightx = 0.75;
		this.spnNumberLines = new JSpinner(new SpinnerNumberModel(15, 10, null, 1));
		this.spnNumberLines.setValue(this.getNumberOfLines());
		this.spnNumberLines.addChangeListener(this);
		this.panel.add(this.spnNumberLines, c);		

		//max width of each line
		c.gridx = 0; c.gridy++; c.weightx = 0.25;
		this.panel.add(new JLabel(str.get("OPTION_MAX_WIDTH")), c);
		
		c.gridx = 1; c.weightx = 0.75;
		this.spnMaxWidth = new JSpinner(new SpinnerNumberModel(1, 1, null, 1));
		this.spnMaxWidth.setValue(this.getMaxWidth());
		this.spnMaxWidth.addChangeListener(this);
		this.panel.add(this.spnMaxWidth, c);
		
		//max displacement
		c.gridx = 0; c.gridy++; c.weightx = 0.25;
		this.panel.add(new JLabel(str.get("OPTION_MAX_DISPLACEMENT")), c);
		
		c.gridx = 1; c.weightx = 0.75;
		this.spnDisplacement = new JSpinner(new SpinnerNumberModel(1, 0, null, 1));
		this.spnDisplacement.setValue(this.getDisplacement());
		this.spnDisplacement.addChangeListener(this);
		this.panel.add(this.spnDisplacement, c);			

		//noise's random seed
		c.gridx = 0; c.gridy++; c.weightx = 0.25;
		JButton btn = new JButton(str.get("OPTION_RANDOM_SEED"));
		btn.setActionCommand("OPTION_RANDOM_SEED");
		btn.addActionListener(this);
		this.panel.add(btn, c);
		
		c.gridx = 1; c.weightx = 0.75;
		this.lblSeed = new JLabel(this.getSeed() + "", JLabel.CENTER);
		this.panel.add(this.lblSeed, c);			

		//empty panel to push everything to the top
		c.gridx = 0; c.gridy++; c.weighty = 1; 
		this.panel.add(new JPanel(), c);
		
		this.isLoadingPreset = false;
	}
	
	@Override
	public JPanel getPanel() {
		return this.panel;
	}

	@Override
	public String getName() {
		return this.strings.get("SCREENTONE_NAME");
	}

	@Override
	public String getUID() {
		return "B0D96BCDFEF0421FBF3FC6D04B602982";
	}

	@Override
	public void loadPreset(Element node) {

		//first load the values internally for the screentone
		super.loadPreset(node);
		
		//temporarily turn off updating
		this.isLoadingPreset = true;
						
		this.spnCenterX.setValue(this.getCenterX());
		this.spnCenterY.setValue(this.getCenterY());
		this.spnRadius1.setValue(this.getRadiusA());
		this.spnRadius2.setValue(this.getRadiusB());
		this.spnNumberLines.setValue(this.getNumberOfLines());
		this.spnMaxWidth.setValue(this.getMaxWidth());
		this.spnDisplacement.setValue(this.getDisplacement());
		this.lblSeed.setText(this.getSeed() + "");

		//turn it back on
		this.isLoadingPreset = false;
	}
	
	@Override
	public void stateChanged(ChangeEvent event) {
		
		if (this.isLoadingPreset)
			return;
		
		if (event.getSource() == this.spnCenterX)
			this.setCenterX((int)this.spnCenterX.getValue());

		else if (event.getSource() == this.spnCenterY)
			this.setCenterY((int)this.spnCenterY.getValue());

		else if (event.getSource() == this.spnRadius1)
			this.setRadiusA((int)this.spnRadius1.getValue());
		
		else if (event.getSource() == this.spnRadius2)
			this.setRadiusB((int)this.spnRadius2.getValue());

		else if (event.getSource() == this.spnNumberLines)
			this.setNumberOfLines((int)this.spnNumberLines.getValue());

		else if (event.getSource() == this.spnMaxWidth)
			this.setMaxWidth((int)this.spnMaxWidth.getValue());
		
		else if (event.getSource() == this.spnDisplacement)
			this.setDisplacement((int)this.spnDisplacement.getValue());
				
		raisePropertyChangedEvent();
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		Random rnd = new Random();
		long newSeed = rnd.nextLong();
		this.setSeed(newSeed);
		this.lblSeed.setText(newSeed + "");
		
		raisePropertyChangedEvent();
		
	}

}
